# Configuration for Microsoft Build Engine

LINKER = link
AR = lib
CP = copy
MV = move
RM = del


# See win32.mak for details. 

!include <win32.mak>
#!include <C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include\win32.mak>


# Configuration for Microsoft Visual C++

CC = cl
CFLAGS = $(cflags) -DHAVE_CONFIG_WIN_H -I../include -w 

!ifdef msvcrt
CFLAGS = $(CFLAGS) $(cvarsdll)
LDFLAGS = $(LDFLAGS) $(conlflags) $(conlibsdll)
!ifdef omp
CFLAGS = $(CFLAGS) -openmp
!endif
!else
!ifdef omp
CFLAGS = $(CFLAGS) $(cvarsmt) -openmp
LDFLAGS = $(LDFLAGS) $(conlibsmt) 
!else
CFLAGS = $(CFLAGS) $(cvars)
LDFLAGS = $(LDFLAGS) $(conlibs)
!endif
!endif

CFLAGS = $(cdebug) $(CFLAGS) $(USER_CFLAGS)
LDFLAGS = $(ldebug) $(conlflags) $(LDFLAGS) $(USER_LDFLAGS)


# Configuration for Intel FPU

!ifndef noifpu
CFLAGS = $(CFLAGS) -DHAS_X87_FPU -DUSE_QUAD_PRECISION -DUSE_FMA2_SSE2 -DUSE_SSE2 -DUSE_FAST_QUAD_ADD
!endif


# Configuration for Intel C Compiler 

!ifdef intelc
!ifdef icllvm
CC = icx
!else
CC = icl
!endif
CFLAGS = $(cflags) $(USER_CFLAGS) \
       -O3 -Qansi_alias -Qstd=c99 -DHAVE_CONFIG_WIN_H -DHAVE_COMPLEX_H -I../include -w 

!ifdef omp
!ifdef icllvm
CFLAGS = $(CFLAGS) $(cdebug) $(cvarsmt) -Qiopenmp -Qopenmp-lib:compat
!else
CFLAGS = $(CFLAGS) $(cdebug) $(cvarsmt) -Qopenmp -Qopenmp-lib:compat
!endif
!else
CFLAGS = $(CFLAGS) $(cdebug) $(cvars)
!endif

!ifdef impi
!ifdef icllvm
CC = mpiicc -cc=icx
!else
CC = mpiicc
!endif
CFLAGS = $(CFLAGS) -DUSE_MPI
LINKER = mpiicc
LDFLAGS =
!endif
!endif


# Configuration for Fortran interface

!ifdef fortran
FC = ifort
CFLAGS = $(CFLAGS) -DUSE_FORTRAN
FFLAGS = $(USER_FFLAGS) \
       -c -O3 -fpp -Qansi_alias -DZERO_ORIGIN=1 -I../include -I../src/fortran/amg -w 

!ifdef omp
FFLAGS = $(FFLAGS) -Qopenmp -Qopenmp-lib:compat 
!else
FFLAGS = $(FFLAGS) -MT
!endif

!ifdef impi
FC = mpiifort
FFLAGS = $(FFLAGS) -DUSE_MPI
LINKER = mpiifort
LDFLAGS =
!endif
!endif


# Configuration for SA-AMG preconditioning

!ifdef saamg
CFLAGS = $(CFLAGS) -DUSE_SAAMG
!endif


# Configuration for 64bit integer

!ifdef longlong
CFLAGS = $(CFLAGS) -D_LONG__LONG
FFLAGS = $(FFLAGS) -DLONG__LONG 
!ifdef intel
FFLAGS = $(FFLAGS) -integer-size:64
!endif
!endif


# Configuration for long double precision operations

!ifdef longdouble
CFLAGS = $(CFLAGS) -D_LONG__DOUBLE
FFLAGS = $(FFLAGS) -DLONG__DOUBLE
!ifdef intel
CFLAGS = $(CFLAGS) -Qlong-double
FFLAGS = $(FFLAGS) -real-size:128
!endif
!endif


# Configuration for complex arithmetic

!ifdef complex
CFLAGS = $(CFLAGS) -DUSE_COMPLEX -D_COMPLEX
FFLAGS = $(FFLAGS) -DCOMPLEX
!endif


# Configuration for Microsoft MPI

!ifdef msmpi32
MPIDIR = "C:\Program Files (x86)\Microsoft SDKs\MPI"
CFLAGS = $(CFLAGS) -DUSE_MPI -I$(MPIDIR)\Include
FFLAGS = $(FFLAGS) -DUSE_MPI -I$(MPIDIR)\Include -I$(MPIDIR)\Include\x86
LDFLAGS = $(LDFLAGS) $(MPIDIR)\Lib\x86\msmpi.lib $(MPIDIR)\Lib\x86\msmpifec.lib
MPIRUN = "mpiexec -n 2"
!endif

!ifdef msmpi64
MPIDIR = "C:\Program Files (x86)\Microsoft SDKs\MPI"
CFLAGS = $(CFLAGS) -DUSE_MPI -I$(MPIDIR)\Include
FFLAGS = $(FFLAGS) -DUSE_MPI -I$(MPIDIR)\Include -I$(MPIDIR)\Include\x64
LDFLAGS = $(LDFLAGS) $(MPIDIR)\Lib\x64\msmpi.lib $(LDFLAGS) $(MPIDIR)\Lib\x64\msmpifec.lib
MPIRUN = "mpiexec -n 2"
!endif


# Configuration for Intel MPI

!ifdef impi
MPIRUN = "mpiexec -n 2"
!endif


!ifdef notest
!ifdef fortran
all: libs libs_lisf_init
!else
all: libs
!endif
!else
!ifdef fortran
all: libs exes_test exes_etest exes_spmvtest \
     libs_lisf_init exes_testf exes_etestf
!ifdef saamg
!ifdef impi
all: libs exes_test exes_etest exes_spmvtest \
     libs_lisf_init exes_testf exes_etestf test8f.exe
!endif
!endif
!else
all: libs exes_test exes_etest exes_spmvtest
!endif
!endif

!ifdef saamg
libs: objs_array objs_esolver objs_fortran objs_matrix objs_matvec \
      objs_precision objs_precon objs_solver objs_system objs_vector objs_saamg 
!else
libs: objs_array objs_esolver objs_fortran objs_matrix objs_matvec \
      objs_precision objs_precon objs_solver objs_system objs_vector
!endif
	$(AR) *.obj -out:lis.lib

objs_array: ..\src\array\*.obj 
objs_esolver: ..\src\esolver\*.obj 
objs_fortran: ..\src\fortran\*.obj 
objs_matrix: ..\src\matrix\*.obj 
objs_matvec: ..\src\matvec\*.obj 
objs_precision: ..\src\precision\*.obj 
objs_precon: ..\src\precon\*.obj 
objs_solver: ..\src\solver\*.obj 
objs_system: ..\src\system\*.obj 
objs_vector: ..\src\vector\*.obj

!if defined(msmpi32) || defined(msmpi64) || defined(impi) 
objs_saamg: ..\src\fortran\amg\lis_m_data_structure_for_AMG.obj \
	    ..\src\fortran\amg\lis_m_queue_mod.obj \
	    ..\src\fortran\amg\lis_m_hash_mod.obj \
	    ..\src\fortran\amg\lis_m_solver_Gnumbering.obj \
	    ..\src\fortran\amg\lis_m_solver_SR2.obj \
	    ..\src\fortran\amg\lis_m_aggregate_mod.obj \
	    ..\src\fortran\amg\lis_m_count_time_mod.obj \
	    ..\src\fortran\amg\lis_m_isort.obj \
	    ..\src\fortran\amg\lis_m_data_creation_AMGCG.obj \
	    ..\src\fortran\amg\lis_m_solver_AMGCG.obj \
	    ..\src\fortran\amg\lis_m_finit.obj 
!else
objs_saamg: ..\src\fortran\amg\lis_s_data_structure_for_AMG.obj \
	    ..\src\fortran\amg\lis_s_queue_mod.obj \
	    ..\src\fortran\amg\lis_s_aggregate_mod.obj \
	    ..\src\fortran\amg\lis_s_isort.obj \
	    ..\src\fortran\amg\lis_s_data_creation_AMGCG.obj \
	    ..\src\fortran\amg\lis_s_solver_AMGCG.obj \
	    ..\src\fortran\amg\lis_s_finit.obj
!endif

exes_test: test1.exe test2.exe test2b.exe test3.exe test3b.exe test3c.exe test4.exe test5.exe test6.exe
exes_etest: etest1.exe getest1.exe etest2.exe etest3.exe etest4.exe etest5.exe etest5b.exe getest5.exe getest5b.exe etest6.exe etest7.exe
exes_spmvtest: spmvtest1.exe spmvtest2.exe spmvtest2b.exe spmvtest3.exe spmvtest3b.exe spmvtest4.exe spmvtest5.exe

exes_testf: test1f.exe test2f.exe test4f.exe test6f.exe
exes_etestf: etest1f.exe etest4f.exe

test1.exe: ..\test\$*.obj
test2.exe: ..\test\$*.obj
test2b.exe: ..\test\$*.obj
test3.exe: ..\test\$*.obj
test3b.exe: ..\test\$*.obj
test3c.exe: ..\test\$*.obj
test4.exe: ..\test\$*.obj
test5.exe: ..\test\$*.obj
test6.exe: ..\test\$*.obj
etest1.exe: ..\test\$*.obj
getest1.exe: ..\test\$*.obj
etest2.exe: ..\test\$*.obj
etest3.exe: ..\test\$*.obj
etest4.exe: ..\test\$*.obj
etest5.exe: ..\test\$*.obj
etest5b.exe: ..\test\$*.obj
getest5.exe: ..\test\$*.obj
getest5b.exe: ..\test\$*.obj
etest6.exe: ..\test\$*.obj
etest7.exe: ..\test\$*.obj
spmvtest1.exe: ..\test\$*.obj
spmvtest2.exe: ..\test\$*.obj
spmvtest2b.exe: ..\test\$*.obj
spmvtest3.exe: ..\test\$*.obj
spmvtest3b.exe: ..\test\$*.obj
spmvtest4.exe: ..\test\$*.obj
spmvtest5.exe: ..\test\$*.obj

libs_lisf_init:
	$(FC) $(FFLAGS) ..\src\fortran\lisf_init.f lis.lib -out:lisf_init.obj
	$(AR) lis.lib lisf_init.obj -out:lis.lib

test1f.exe: ..\test\$*.obj
	$(LINKER) $(LDFLAGS) $*.obj lis.lib

test2f.exe: ..\test\$*.obj
	$(LINKER) $(LDFLAGS) $*.obj lis.lib

test4f.exe: ..\test\$*.obj
	$(LINKER) $(LDFLAGS) $*.obj lis.lib

test6f.exe: ..\test\$*.obj
	$(LINKER) $(LDFLAGS) $*.obj lis.lib

test8f.exe: ..\test\$*.obj
	$(LINKER) $(LDFLAGS) $*.obj lis.lib

etest1f.exe: ..\test\$*.obj
	$(LINKER) $(LDFLAGS) $*.obj lis.lib

etest4f.exe: ..\test\$*.obj
	$(LINKER) $(LDFLAGS) $*.obj lis.lib 

.c.obj:
	$(CC) $(CFLAGS) $*.c

.f.obj:
	$(FC) $(FFLAGS) $*.f 

.f90.obj:
	$(FC) $(FFLAGS) $*.f90

.obj.exe:
	$(LINKER) $(LDFLAGS) $*.obj lis.lib 

check:
!ifdef omp
	@set OMP_NUM_THREADS=2
!else
	@set OMP_NUM_THREADS=1
!endif
	@echo checking linear solvers...
	@$(MPIRUN) test1.exe ..\test\testmat.mtx 0 nul nul
	@echo checking eigensolvers...
	@$(MPIRUN) etest1.exe ..\test\testmat.mtx nul nul
!ifdef fortran
	@echo checking Fortran interface...
	@echo.
	@$(MPIRUN) test4f.exe
	@echo.
!endif
!ifdef saamg
	@echo SAAMG preconditioner...
	@$(MPIRUN) test2.exe 10 10 1 nul nul -i cg -p saamg
!endif

install:
	if not exist $(PREFIX) mkdir $(PREFIX)
	if not exist $(PREFIX)\include mkdir $(PREFIX)\include
	if not exist $(PREFIX)\lib mkdir $(PREFIX)\lib
	if not exist $(PREFIX)\doc mkdir $(PREFIX)\doc
	$(CP) lis.lib $(PREFIX)\lib
	$(CP) ..\include\lis_config_win.h $(PREFIX)\include
	$(CP) ..\include\lis.h $(PREFIX)\include
	$(CP) ..\include\lisf.h $(PREFIX)\include
	$(CP) ..\doc\lis-ug-en.pdf $(PREFIX)\doc
	$(CP) ..\doc\lis-ug-ja.pdf $(PREFIX)\doc
!ifndef notest
	if not exist $(PREFIX)\bin mkdir $(PREFIX)\bin
	$(CP) test1.exe $(PREFIX)\bin\lsolve.exe
	$(CP) etest5.exe $(PREFIX)\bin\esolve.exe
	$(CP) etest5b.exe $(PREFIX)\bin\esolver.exe
	$(CP) getest5.exe $(PREFIX)\bin\gesolve.exe
	$(CP) getest5b.exe $(PREFIX)\bin\gesolver.exe
	$(CP) test3b.exe $(PREFIX)\bin\hpcg_kernel.exe
	$(CP) spmvtest3b.exe $(PREFIX)\bin\hpcg_spmvtest.exe
	$(CP) spmvtest1.exe $(PREFIX)\bin
	$(CP) spmvtest2.exe $(PREFIX)\bin
	$(CP) spmvtest2b.exe $(PREFIX)\bin
	$(CP) spmvtest3.exe $(PREFIX)\bin
	$(CP) spmvtest3b.exe $(PREFIX)\bin
	$(CP) spmvtest4.exe $(PREFIX)\bin
	$(CP) spmvtest5.exe $(PREFIX)\bin
!endif

uninstall:
	$(RM) $(PREFIX)\lib\lis.lib
	$(RM) $(PREFIX)\include\lis_config_win.h
	$(RM) $(PREFIX)\include\lis.h
	$(RM) $(PREFIX)\include\lisf.h
	$(RM) $(PREFIX)\doc\lis-ug-en.pdf
	$(RM) $(PREFIX)\doc\lis-ug-ja.pdf
	rmdir $(PREFIX)\lib $(PREFIX)\include $(PREFIX)\doc
!ifndef notest
	$(RM) $(PREFIX)\bin\lsolve.exe
	$(RM) $(PREFIX)\bin\esolve.exe
	$(RM) $(PREFIX)\bin\esolver.exe
	$(RM) $(PREFIX)\bin\gesolve.exe
	$(RM) $(PREFIX)\bin\gesolver.exe
	$(RM) $(PREFIX)\bin\hpcg_kernel.exe
	$(RM) $(PREFIX)\bin\hpcg_spmvtest.exe
	$(RM) $(PREFIX)\bin\spmvtest1.exe
	$(RM) $(PREFIX)\bin\spmvtest2.exe
	$(RM) $(PREFIX)\bin\spmvtest2b.exe
	$(RM) $(PREFIX)\bin\spmvtest3.exe
	$(RM) $(PREFIX)\bin\spmvtest3b.exe
	$(RM) $(PREFIX)\bin\spmvtest4.exe
	$(RM) $(PREFIX)\bin\spmvtest5.exe
	rmdir $(PREFIX)\bin
!endif
	rmdir $(PREFIX)

clean:
	$(RM) *.obj *.mod *.pdb 

distclean: 
	$(RM) *.lib *.exe *.obj *.mod *.pdb Makefile

